'''
BaiduImage V1.0
By SkyFire
QQ:1513008876
E-Mail:skyfireitdiy@hotmail.com
'''


import httplib2
from urllib.parse import urlencode
import json
import os
import errno
import threading


class BaiduImage:
    __g_http_client = httplib2.Http('.Cache')

    def __search(self,keyword,page):
        '''
        搜索图片数据
        :param keyword: 关键字
        :param page: 页码
        :return: 结果列表
        '''
        try:
            data={
                'tn':'resultjson_com',
                'ipn':'rj',
                'fp':'result',
                'queryWord':keyword,
                'ie':'utf-8',
                'oe':'utf-8',
                'word':keyword,
                'pn':page}
            print('request: '+'https://image.baidu.com/search/acjson?'+urlencode(data))
            response, content = self.__g_http_client.request('https://image.baidu.com/search/acjson?'+urlencode(data),
                                                             headers={'Content-Type': 'application/x-www-form-urlencoded'})
            ret_data = []
            if response['status']=='200':
                ret=json.loads(content.decode('utf-8'))
                if 'data' in ret:
                    for i in range(len(ret['data'])-1):
                        if 'replaceUrl' in ret['data'][i]:
                            tp=ret['data'][i]['replaceUrl']
                            for j in tp:
                                ret_data.append({'high':j['ObjURL'],'low':ret['data'][i]['thumbURL']})
                        else:
                            ret_data.append({'low':ret['data'][i]['thumbURL']})
                else:
                    print(content.decode('utf-8'))
            else:
                print(response)
            return ret_data
        except:
            print('__search except')
            return []

    def __mkdir(self, dir_path):
        '''
        递归创建文件夹
        :param dir_path: 文件夹路径
        '''
        if not dir_path.endswith('/'):
            index = dir_path.rfind('/')
            if index == -1:
                return
            dir_path = dir_path[:index + 1]
        try:
            os.makedirs(dir_path)
        except OSError as exc:
            if exc.errno == errno.EEXIST and os.path.isdir(dir_path):
                pass
            else:
                raise

    def __get_filename(self,url):
        '''
        从url获取文件名
        :param url:URL
        :return: 文件名
        '''
        index=url.rfind('/')
        if index!=-1:
            return url[index+1:]
        return ''

    def __download(self,url,save_path):
        '''
        下载图片
        :param url:图片URL
        :param save_path:保存路径
        :return: 下载结果
        '''
        try:
            print('downloading '+url)
            file_name=save_path+self.__get_filename(url)
            if os.path.exists(file_name):
                print('file '+file_name+' exist')
                return False
            response, content = self.__g_http_client.request(url,
                                                             headers={'Content-Type': 'application/x-www-form-urlencoded'})
            if response['status']=='206' or response['status']=='200':
                fp=open(file_name,'wb')
                if fp:
                    fp.write(content)
                    fp.close()
                    print('download '+file_name)
                    return True
                else:
                    print(file_name+' open error')
            else:
                print('status error, response:')
                print(response)
            return False
        except:
            print('__download except')
            return False

    def __download_choose(self,url,save_path):
        '''
        选择下载图片,优先高质量的图片
        param url:图片url
        param save_path:保存路径
        return 返回true表示成功,否则失败
        '''
        if 'high' in url:
            if self.__download(url['high'],save_path):
                return True
        return self.__download(url['low'],save_path)


    def get_image(self,keyword,count,start_page,save_path):
        '''
        获取图片
        :param keyword:关键字
        :param count: 数量
        :param start_page: 起始页码
        :param save_path: 保存位置
        '''
        if not (save_path.endswith('/') or save_path.endswith('\\')):
            save_path += '/'
        save_path+=key_word+'/'
        if not os.path.exists(save_path):
            self.__mkdir(save_path)
        num=0
        net_index=start_page
        error_time=0
        while num<count:
            lst=self.__search(keyword,net_index)
            print('get '+str(len(lst))+ ' urls')
            if len(lst)==0:
                error_time+=1
                if error_time>=5:
                    print('error 5 times, exit')
                    break
            for i in lst:
                if self.__download_choose(i,save_path):
                    num+=1
                    if num>=count:
                        break
            net_index+=1


if __name__=='__main__':
    clawler=BaiduImage()
    key_word=input('key word:')
    count=int(input('count:'))
    start_page=int(input('start page:'))
    save_path = input('save path:')
    clawler.get_image(key_word,count,start_page,save_path)
